from django.shortcuts import render, redirect
# 导包
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
# 导入类视图
from django.views import View

# from myapp.models import User
import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
# 导入加密库
import hashlib
# 导入图片库
# 绘画库
from PIL import ImageDraw
# 字体库
from PIL import ImageFont
# 图片库
from PIL import Image
# 随机库
import random
# 文件流
import io

import requests

# 导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

# 导入原生sql模块
from django.db import connection

import jwt

# 导入redis数据库
import redis

# 导入时间模块
import time

# 导入公共目录变量
from mydjango.settings import BASE_DIR

# 导包
from django.db.models import Q, F

# 导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

from myapp.models import User

from myapp.myser import UserSer

import jwt


#导入钉钉三方登录所需库
import hmac
import base64
from hashlib import sha256
import urllib

# 导入中间件包
from django.utils.deprecation import MiddlewareMixin


# 自定义中间件
class MyMiddleWare(MiddlewareMixin):

    # 请求之前
    def process_request(self, request):
        # uid = request.GET.get("uid")
        # clinet_jwt = request.GET.get("jwt", None)
        #
        # if clinet_jwt == None:
        #
        #     return HttpResponse('你没有带上令牌')
        #
        # # print(uid)
        # # print(clinet_jwt)
        # # print(type(clinet_jwt))
        #
        # decode_jwt = jwt.decode(clinet_jwt, '123', algorithms=['HS256'])
        #
        # if (str(decode_jwt['uid']) != str(uid)):
        #     return HttpResponse('你篡改了用户id')
        pass


    #模板渲染之前
    def process_view(self,request,view_func,view_args,view_kwargs):
        pass

    #请求之后
    def process_response(self,request,response):
        return response


#装饰器的使用
def my_decorator(func):
    def wrapper(request,*args,**kwargs):
        print('这个装饰器被调用了')
        print('请求接口地址是: %s' % request.path)

        #判断jwt逻辑
        uid = request.GET.get("uid")
        clinet_jwt = request.GET.get("jwt", None)

        decode_jwt = jwt.decode(clinet_jwt, '123', algorithms=['HS256'])
        if (str(decode_jwt['uid']) != str(uid)):
            return HttpResponse('你篡改了用户id')

        return func(request,*args,**kwargs)
    return wrapper

#类装饰器调用
from django.utils.decorators import method_decorator


#创建MD5加密
def make_password(mypass):
    #生成MD5对象
    md5 = hashlib.md5()
    #定义加密对象
    sign_str = str(mypass)
    #转码
    sign_utf8 = sign_str.encode(encoding='utf-8')
    #加密
    md5.update(sign_utf8)
    #生成密钥串
    md5_server = md5.hexdigest()

    return md5_server

#导入redis
import redis

#定义ip地址和端口
host = '127.0.0.1'
port = 6379

#生成链接对象
r = redis.Redis(host=host,port=port)


# #定义docker 环境中的IP地址和端口
# docker_host = '192.168.99.100'
# docker_port = 6380
#
# #生成docker 环境中的链接对象
# docker_r = redis.Redis(host=docker_host,port=docker_port)

#手写随机验证码类
class MyCode(View):

    #定义随机颜色
    def get_random_color(self):
        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)

        return (R,G,B)

    #定义获取验证码视图
    def get(self,request):
        #定义画布
        img_size = (120,50)
        #定义画图对象
        image = Image.new('RGB',img_size,'white')
        #定义画笔对象
        draw = ImageDraw.Draw(image,'RGB')
        #定义随机字符串
        source = '0123456789'
        '''
        #定义中文随机字符串
        '''
        # source = "你好我好大家好才是真的好"
        #定义容器
        code_str = ''
        #定义字体
        my_font = ImageFont.truetype(font='C:\\Windows\\Fonts\\cambriaz.ttf',size=16)
        '''
        #定义中文字体
        '''
        #my_font = ImageFont.truetype(font='C:\\Windows\\Fonts\\msyh.ttc',size=16)
        #向容器内加入验证码
        for i in range(4):
            #获取随机颜色
            text_color = self.get_random_color()
            #获取随机字符串长度下标
            tmp_num = random.randrange(len(source))
            #获取字符集
            random_str = source[tmp_num]
            #获取到后立刻添加到容器中
            code_str += random_str
            #将字符串添加到画布
            draw.text((10+30*i,20),random_str,text_color,font=my_font)   #横纵坐标,设定的字符串,颜色
        #建立缓存区
        buf = io.BytesIO()
        #保存图片
        image.save(buf,'png')

        #将随机验证码存入redis保存
        r.set('code',code_str)

        # #将随机验证码存入dicker 环境下的redis中保存
        # docker_r.set('docker_code',code_str)

        #将随机验证码存入session中保存
        request.session['code'] = code_str

        #返回图片并渲染
        return HttpResponse(buf.getvalue(),'image/png')


#用户注册模块
class Register(APIView):
    def get(self,request):
        #接收参数
        username = request.GET.get('username','null')
        password = request.GET.get('password','null')
        code = request.GET.get('code','null')

        print(username)
        print(password)
        print("web_code :",code)

        #获取redis库内保存的验证码
        redis_code = r.get('code')
        # 进行转码操作
        redis_code = redis_code.decode('utf-8')
        # 打印查看验证码
        print("redis_code :",redis_code)

        # #获取docker 环境中的随机验证码
        # docker_redis_code = docker_r.get('docker_code')
        # #进行转码操作
        # docker_redis_code = docker_redis_code.decode('utf-8')
        # #打印查看docker内redis中存储的验证码
        # print('docker_redis_code :',docker_redis_code)


        #获取session内保存的验证码
        # session_code = request.session.get('code')
        # print("session_code :",session_code)

        #判断是否正确
        if code != redis_code:
        # if code != session_code:
            res = {}
            res['code'] = 405
            res['message'] = '验证码输入错误'

            return Response(res)

        #排重
        user = User.objects.filter(username=username).first()

        if user:
            res = {}
            res['code'] = 405
            res['message'] = "该用户名已存在,请勿重复注册"

            return Response(res)
        else:
            user = User(username = username,password = make_password(password),img='',type=0)
            user.save()

            res = {}
            res['code'] = 200
            res['message'] = "用户注册成功,请登录"

            return Response(res)



class Login(APIView):
    def get(self,request):
        #接收参数
        username = request.GET.get('username','null')
        password = request.GET.get('password','null')

        #查询数据
        user = User.objects.filter(username=username,password=make_password(password)).first()

        #判断
        if user:
            res = {}
            res['code'] = 200
            res['message'] = "登录成功"

            #返回username
            res['username'] = user.username
            #返回uid
            res['uid'] = user.id

            #加入jwt令牌机制
            encode_jwt = jwt.encode({'uid': user.id}, '123', algorithm='HS256')
            print(encode_jwt)
            # 解码操作
                # 强转
            encode_str = str(encode_jwt, 'utf-8')
            res['jwt'] = encode_str

            return Response(res)

        else:
            res = {}
            res['code'] = 405
            res['message'] = "用户名或密码错误,请重试"

            return Response(res)


# 新浪微博回调方法
def wb_back(request):

    #获取cdoe
    code = request.GET.get('code')
    #定义微博认证地址
    access_token_url = 'https://api.weibo.com/oauth2/access_token'
    #定义参数
    res = requests.post(
    access_token_url,
    data = {
        'client_id':'3800897608',
        'client_secret':'83c24c00a5194e3d648d07438c6aabda',
        'grant_type':'authorization_code',
        'code':code,
        'redirect_uri':"http://127.0.0.1:8000/md_admin/weibo"
    }
)

    #转换类型
    res = json.loads(res.text)

    print(res)
    # return HttpResponse(res['uid'])

    #获取新浪微博昵称
    result = requests.get('https://api.weibo.com/2/users/show.json',params={
        'access_token':res['access_token'],
        'uid':res['uid'],

    })

    print(result.text)
    result = json.loads(result.text)

    #判断该用户是否曾经登陆过
    user = User.objects.filter(username = str(result['name'])).first()

    sina_id = ''
    user_id = ''

    #如果找到了
    if user:

        sina_id = user.username
        user_id = user.id

    else:
        #手动创建一个账号
        user = User(username = str(result['name']),password = '',img = '',type = 0)
        user.save()

        sina_id = result['name']
        #查询入库的新账号id
        user = User.objects.filter(username = str(result['name'])).first()
        user_id = user.id

    # return HttpResponse(result['name'])\
    #进行跳转
    return redirect('http://127.0.0.1:8080?sina_id='+sina_id+'&uid='+str(user_id))


#拿取新浪微博用户名创建账号
'''
    # #将返回的数据转换成dict
    # res_dict = dict(res)
    #
    # user = User.objects.filter(username=str(res_dict['uid'])).first()
    #
    # sina_username = ''
    # sina_uid = ''
    #
    # if user:
    #     sina_username = user.username
    #     sina_uid = user.id
    #
    # else:
    #     #自动生成微博登陆账号
    #     user = User(username=str(res_dict['uid']),password=make_password(123),img='',type=0)
    #     #保存
    #     user.save()
    #
    #     #查询用户id
    #     user = User.objects.filter(username=str(res_dict['uid'])).first()
    #
    #     #赋值
    #     sina_username = str(res_dict['uid'])
    #     sina_uid = user.id
    #
    # print(sina_username)
    # print(sina_uid)
    #
    # return redirect('http://127.0.0.1:8080?sina_id=' + str(sina_username) + '&sina_uid=' + str(sina_uid))
    # return HttpResponse(sina_username)
    '''


#构造钉钉回调方法
def ding_back(request):

    #获取code
    code = request.GET.get("code")

    t = time.time()
    #时间戳
    timestamp = str((int(round(t * 1000))))
    appSecret ='ly-AzMKMmCKQP3geaILT_An32kEfKO3HeOtApy5CgKwjytevVZC0WYsT2gxMB160'
    #构造签名
    signature = base64.b64encode(hmac.new(appSecret.encode('utf-8'),timestamp.encode('utf-8'), digestmod=sha256).digest())
    #请求接口，换取钉钉用户名
    payload = {'tmp_auth_code':code}
    headers = {'Content-Type': 'application/json'}
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature='+urllib.parse.quote(signature.decode("utf-8"))+"&timestamp="+timestamp+"&accessKey=dingoaukgkwqknzjvamdqh",data=json.dumps(payload),headers=headers)

    res_dict = json.loads(res.text)
    print(res_dict['user_info']['nick'])

    #排重操做
    user = User.objects.filter(username=str(res_dict['user_info']['nick'])).first()

    ding_name = ''
    ding_id = ""
    if user:
        ding_name = str(res_dict['user_info']['nick'])
        ding_id = user.id

    else:
        #自动创建钉钉登录用户
        user = User(username=str(res_dict['user_info']['nick']),password='',img='',type='0')
        user.save()

        ding_name = str(res_dict['user_info']['nick'])
        user = User.objects.filter(username=str(res_dict['user_info']['nick'])).first()

        ding_id = user.id

    # return HttpResponse(res_dict['user_info']['nick'])
    #展示钉钉三方登录状态
    return redirect('http://127.0.0.1:8080?ding_name=' + str(res_dict['user_info']['nick']) + '&ding_id=' + str(ding_id))


#定义上传视图类
class UploadFile(View):
    def post(self,request):
        img = request.FILES.get('file')
        print(img)

        #建立文件流对象
        f = open(os.path.join(UPLOAD_ROOT,'',img.name),'wb')

        #写入服务器端
        for chunk in img.chunks():
            f.write(chunk)

        f.close()

        # 打开图片
        im = Image.open('./static/upload/'+str(img))
        print(im.size)

        # 生成画笔
        draw = ImageDraw.Draw(im)

        # 修改(添加水印)
        draw.text((0, 0), 'Rliner', fill=(76, 234, 124, 180))

        # 查看图片
        # im.show()

        # 存储图片
        im.save('./static/upload/'+str(img))

        #返回文件名
        return HttpResponse(json.dumps({'filename':img.name},ensure_ascii=False),content_type ='application/json')


#构造用户主页密码修改接口
class Upload_User(APIView):

    def get(self,request):
        password = request.GET.get('password')
        password_one = request.GET.get('password_one')
        uid = request.GET.get('uid')

        user = User.objects.filter(id=uid).first()

        if password != password_one:
            res = {}
            res['code'] = 405
            res['message'] = "两次输入的密码不一致,请重新输入"

            return Response(res)

        if user:
            user.password = make_password(password)
            user.save()

            res = {}
            res['code'] = 200
            res['message']= "密码修改成功"

            return Response(res)
        else:
            res = {}
            res['code'] = 405
            res['message'] = '密码修改失败'

            return Response(res)


#七牛云文件存储接口
from qiniu import Auth

class QiNiu(APIView):

    def get(self,request):
        #定义密钥
        q = Auth('mUmfcgbMzk3xCQa8YuQ6hU9Vw61vzfp_JqZtRN7h','D-P4fTBTsISm-3KSWOznU5_i1wzeARTsO6ZkWTMb')

        #指定上传空间
        token = q.upload_token('rliner')

        # print(token)

        res = {}
        res['token'] = token

        return Response(res)


#用户信息类
class UserInfo(APIView):

    #装饰器调用
    # @method_decorator(my_decorator)
    #返回用户信息
    def get(self,request):
        uid = request.GET.get('uid')

        #查询数据
        user = User.objects.get(id=int(uid))

        #序列化对象
        user_ser = UserSer(user,many=False)

        return Response(user_ser.data)


'''
# #用户信息类  COPY
#     #使用jwt
# class UserInfo(APIView):
# 
#     # @outhor
#     def get(self,request):
#         uid = request.GET.get('uid')
# 
#         if uid:
#             # 代表用户曾经登陆过或正在登陆状态
#             user = User.objects.filter(id=uid).first()
# 
#             encode_jwt_user = jwt.encode({'uid': uid}, '123', algorithm='HS256')
#             print("jwt_user: ",encode_jwt_user)
# 
#             # 转码
#             encode_jwt_str = str(encode_jwt_user, 'utf-8')
# 
#             # 解码
#             decode_jwt_user = jwt.decode(encode_jwt_str, '123', algorithms=['HS256'])
#             print("解码后返回的参数: ",decode_jwt_user['uid'])
# 
#             if int(decode_jwt_user['uid']) == user.id:
#                 #查询数据
#                 user = User.objects.get(id=int(decode_jwt_user['uid']))
# 
#                 #序列化对象
#                 user_ser = UserSer(user,many=False)
# 
#                 return Response(user_ser.data)
#             else:
#                 return Response('用户ID不一致,无法返回数据')
'''     #用户信息类  COPY


#更新用户数据接口
class UpdateUser(APIView):


    def get(self,request):
        uid = request.GET.get('uid')
        img = request.GET.get('img','null')
        video = request.GET.get('video','null')

        #查询数据
        user = User.objects.get(id=int(uid))
        if img != 'null':
            user.img = img
            user.save()

            return Response({'code':200,'mesage':'头像数据更新成功'})
        elif video != 'null':
            user.video = video
            user.save()

            return Response({'code':200,'mesage':'视频数据更新成功'})
        else:
            return Response({'code': 405, 'mesage': '出现未知错误,请重新提交'})






































